package com.uinnova.product.eam.web.eam.mvc;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.binary.core.exception.BinaryException;
import com.binary.core.util.BinaryUtils;
import com.binary.framework.exception.ServiceException;
import com.binary.framework.util.ControllerUtils;
import com.binary.framework.web.RemoteResult;
import com.binary.jdbc.Page;
import com.google.common.collect.Lists;
import com.uinnova.product.eam.base.util.EamUtil;
import com.uinnova.product.eam.base.util.StaticParamUtil;
import com.uinnova.product.eam.comm.exception.BusinessException;
import com.uinnova.product.eam.comm.model.es.EamDiagramRelationSys;
import com.uinnova.product.eam.model.*;
import com.uinnova.product.eam.model.asset.EamCiRltCopyDTO;
import com.uinnova.product.eam.model.asset.EamCiRltCopyResult;
import com.uinnova.product.eam.model.bm.VcCiQ;
import com.uinnova.product.eam.model.bm.VcCiSearchPage;
import com.uinnova.product.eam.model.dto.CheckCIAttr;
import com.uinnova.product.eam.model.enums.ArtifactType;
import com.uinnova.product.eam.model.vo.*;
import com.uinnova.product.eam.service.*;
import com.uinnova.product.eam.service.asset.BmConfigSvc;
import com.uinnova.product.eam.web.asset.peer.ArchitectureAssetPeer;
import com.uinnova.product.eam.web.diagram.bean.AttrInfo;
import com.uinnova.product.eam.web.eam.peer.IExportPeer;
import com.uinnova.product.eam.web.integration.bean.VcCiInfo;
import com.uinnova.product.eam.web.integration.bean.VcCiTableInfo;
import com.uinnova.product.eam.web.util.FormatUtil;
import com.uinnova.product.vmdb.comm.bean.QueryPageCondition;
import com.uinnova.product.vmdb.comm.doc.annotation.ModDesc;
import com.uinnova.product.vmdb.comm.doc.annotation.MvcDesc;
import com.uinnova.product.vmdb.comm.model.ci.CCcCi;
import com.uinnova.product.vmdb.comm.model.ci.CcCi;
import com.uinnova.product.vmdb.comm.model.ci.CcCiAttrDef;
import com.uinnova.product.vmdb.comm.util.RestTypeUtil;
import com.uinnova.product.vmdb.provider.ci.bean.CcCiClassInfo;
import com.uinnova.product.vmdb.provider.ci.bean.CcCiInfo;
import com.uinnova.product.vmdb.provider.ci.bean.CiGroupPage;
import com.uinnova.product.vmdb.provider.ci.bean.CiQueryCdt;
import com.uinnova.product.vmdb.provider.search.bean.CcCiSearchPage;
import com.uinnova.project.api.diagram.v2.client.ESDiagramApiClient;
import com.uinnova.project.base.diagram.comm.model.ESDiagram;
import com.uino.bean.cmdb.base.*;
import com.uino.bean.cmdb.business.*;
import com.uino.bean.cmdb.query.ESAttrBean;
import com.uino.bean.cmdb.query.ESCISearchBean;
import com.uino.bean.permission.base.SysUser;
import com.uino.init.api.ApiResult;
import com.uino.util.sys.SysUtil;
import io.micrometer.core.instrument.util.StringUtils;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.mica.xss.core.XssCleanIgnore;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/eam/ci")
@MvcDesc(author = "zjm", desc = "对象管理")
public class EamCiMvc {

    @Autowired
    ICISwitchSvc ciSwitchSvc;
    @Autowired
    IEamCiSvc eamCiSvc;
    @Resource
    IEamCIClassApiSvc ciClassApiSvc;
    @Resource
    IExportPeer exportPeer;
    @Resource
    private EamModelSvc modelSvc;
    @Value("${uino.eam.lib_type.show}")
    String libTypes;
    @Autowired
    private IEamArtifactColumnSvc artifactColumnSvc;
    @Resource
    private ESDiagramApiClient diagramApiClient;

    @Resource
    ArchitectureAssetPeer assetPeer;
    @Autowired
    private EamDiagramRelationSysService diagramRelationSysService;
    @Autowired
    private CiClassLimitUseSvc ciClassLimitUseSvc;
    @Autowired
    private BmConfigSvc bmConfigSvc;

    @RequestMapping("/saveOrUpdate")
    @ModDesc(desc = "保存或更新对象信息(ID存在则更新)", pDesc = "对象数据", pType = CcCiInfo.class, rDesc = "1成功0失败", rType =
            Integer.class)
    public void saveOrUpdate(@RequestParam(defaultValue = "DESIGN") LibType libType,
                             HttpServletRequest request, HttpServletResponse response, @RequestBody CcCiInfo ciInfo) {
        BinaryUtils.checkEmpty(ciInfo.getCi(), "ci");
        if (BinaryUtils.isEmpty(ciInfo.getCi().getOwnerCode())) {
            ciInfo.getCi().setOwnerCode(SysUtil.getCurrentUserInfo().getLoginCode());
        }
        // 校验是否存在架构资产的默认字段
        assetPeer.checkFillAssetDefAttr(ciInfo, libType);
        BinaryUtils.checkEmpty(ciInfo.getCi().getOwnerCode(), "ownerCode");
        BinaryUtils.checkEmpty(ciInfo.getCi().getClassId(), "classId");
        Long id = ciSwitchSvc.saveOrUpdateCI(ciInfo, libType);
        ControllerUtils.returnJson(request, response, id);
    }

    @RequestMapping("/v3/saveOrUpdate")
    @ModDesc(desc = "保存或更新对象信息(ID存在则更新)", pDesc = "对象数据", pType = CcCiInfo.class, rDesc = "1成功0失败", rType =
            Integer.class)
    public void saveOrUpdate(@RequestParam(defaultValue = "DESIGN") LibType libType,
                             @RequestParam(defaultValue = "WRITE") SaveType saveType,
                             HttpServletRequest request, HttpServletResponse response, @RequestBody CcCiInfo ciInfo) {
        BinaryUtils.checkEmpty(ciInfo.getCi(), "ci");
        if (BinaryUtils.isEmpty(ciInfo.getCi().getOwnerCode())) {
            ciInfo.getCi().setOwnerCode(SysUtil.getCurrentUserInfo().getLoginCode());
        }
        BinaryUtils.checkEmpty(ciInfo.getCi().getOwnerCode(), "ownerCode");
        BinaryUtils.checkEmpty(ciInfo.getCi().getClassId(), "classId");
        Long id = ciSwitchSvc.saveOrUpdateCI(ciInfo, libType, saveType);
        ControllerUtils.returnJson(request, response, id);
    }

    @RequestMapping("/v2/saveOrUpdate")
    @XssCleanIgnore  //设置该注解，用于跳过配置得Xss防护
    @ModDesc(desc = "保存或更新对象信息(ID存在则更新)", pDesc = "对象数据", pType = CcCiInfo.class, rDesc = "1成功0失败", rType = Integer.class)
    public void saveOrUpdateV2(@RequestParam(defaultValue = "DESIGN") LibType libType, @RequestParam String diagramId,
                               HttpServletRequest request, HttpServletResponse response, @RequestBody CcCiInfo ciInfo) {
        BinaryUtils.checkEmpty(ciInfo.getCi(), "ci");
        if (BinaryUtils.isEmpty(ciInfo.getCi().getOwnerCode())) {
            ciInfo.getCi().setOwnerCode(SysUtil.getCurrentUserInfo().getLoginCode());
        }
        CcCi ciData = ciInfo.getCi();
        //对存在所属上级元素属性字段的CI，进行自动填充该字段
        modelSvc.fillAttrBelongUpperElement(Lists.newArrayList(ciInfo), diagramId, libType);
        Long id = ciSwitchSvc.saveOrUpdateCI(ciInfo, libType);
        CcCiInfo ciNew = ciSwitchSvc.getCiInfoById(id, libType);
        CiInfoExtend extend = EamUtil.copy(ciNew, CiInfoExtend.class);
        List<ESCIInfo> coverCiList = EamUtil.coverCiInfoList(Collections.singletonList(ciNew));
        Map<String, String> diagramMap = modelSvc.createModelCategory(diagramId, coverCiList, ciData.getOwnerCode(), libType);
        if(!BinaryUtils.isEmpty(diagramMap)){
            extend.setCurrentDiagramId(diagramMap.get(ciNew.getCi().getCiCode()));
        }
        ControllerUtils.returnJson(request, response, extend);
    }

    @RequestMapping("/copyCiListByIds")
    @ModDesc(desc = "保存或更新对象信息(ID存在则更新)", pDesc = "对象数据", pType = CcCiInfo.class, rDesc = "1成功0失败", rType = Integer.class)
    public RemoteResult copyCiListByIds(@RequestBody EamCiRltCopyDTO params) {
        Map<String, ? extends SaveBatchCIContext> contextMap = ciSwitchSvc.copyCiListByIds(params.getCiList(), params.getOwnerCode(), params.getLibType(), params.getPostfix());
        List<ESCIInfo> dbCiList = contextMap.values().stream().map(SaveBatchCIContext::getEsCi).collect(Collectors.toList());
        List<Long> classIds = dbCiList.stream().map(ESCIInfo::getClassId).distinct().collect(Collectors.toList());
        List<ESCIClassInfo> classList = ciClassApiSvc.selectCiClassByIds(classIds);
        Map<Long, ESCIClassInfo> classMap = classList.stream().collect(Collectors.toMap(ESCIClassInfo::getId, each -> each));
        modelSvc.createModelCategory(params.getDiagramId(), dbCiList, params.getOwnerCode(), params.getLibType());
        List<CcCiInfo> result = new ArrayList<>();
        for (ESCIInfo esciInfo : dbCiList) {
            ESCIClassInfo classInfo = classMap.get(esciInfo.getClassId());
            CcCiInfo ciInfo = EamUtil.coverESCIInfo(esciInfo, EamUtil.copy(classInfo.getAttrDefs(), CcCiAttrDef.class), classInfo);
            CiInfoExtend extendCi = EamUtil.copy(ciInfo, CiInfoExtend.class);
            SaveBatchCIContext context = contextMap.get(esciInfo.getCiCode());
            extendCi.setOriginId(context.getOriginCiId());
            extendCi.setOriginCiCode(context.getOriginCiCode());
            result.add(extendCi);
        }
        return new RemoteResult(result);
    }

    @RequestMapping("/copyCiAndRltBatch")
    @ModDesc(desc = "批量复制对象及关系数据", pDesc = "对象及关系数据", pType = String.class, rDesc = "关系及对象信息", rType = Object.class)
    public RemoteResult copyCiAndRltBatch(@RequestBody EamCiRltCopyDTO params) {
        EamCiRltCopyResult result = eamCiSvc.copyCiAndRltBatch(params);
        return new RemoteResult(result);
    }

    @RequestMapping("/v2/saveOrUpdateBatch")
    @ModDesc(desc = "保存或更新对象信息(ID存在则更新)", pDesc = "对象数据", pType = CcCiInfo.class, rDesc = "1成功0失败", rType = Integer.class)
    public void saveOrUpdateBatch(@RequestParam(defaultValue = "DESIGN") LibType libType, @RequestParam String diagramId,
                                  HttpServletRequest request, HttpServletResponse response, @RequestBody List<CcCiInfo> ciList) {
        BinaryUtils.checkEmpty(ciList, "ciList");
        List<Long> classIds = new ArrayList<>();
        Set<String> distinct = new HashSet<>();
        List<CcCiInfo> removeList = new ArrayList<>();
        for (CcCiInfo each : ciList) {
            String ciCode = each.getCi().getCiCode();
            Long classId = each.getCi().getClassId();
            if(BinaryUtils.isEmpty(ciCode) || BinaryUtils.isEmpty(classId)){
                throw new BinaryException("保存的ci数据有误:ciCode="+ciCode+";classId="+classId);
            }
            classIds.add(classId);
            String ciPrimaryKey = each.getCi().getCiPrimaryKey();
            if(ciPrimaryKey !=null && !ciPrimaryKey.equals(ciCode) && distinct.contains(ciPrimaryKey)){
                removeList.add(each);
            }
            distinct.add(ciPrimaryKey);
        }
        ciList.removeAll(removeList);
        Map<String, CcCiInfo> rMap = new HashMap<>();
        if(!CollectionUtils.isEmpty(ciList)){
            //对存在所属上级元素属性字段的CI，进行自动填充该字段
            modelSvc.fillAttrBelongUpperElement(ciList, diagramId, libType);
            String loginCode = SysUtil.getCurrentUserInfo().getLoginCode();
            String ownerCode = ciList.get(0).getCi().getOwnerCode();
            if (BinaryUtils.isEmpty(ownerCode)){
                ownerCode = loginCode;
            }
            List<ESCIInfo> coverCiList = EamUtil.coverCiInfoList(ciList);
            Map<String, ? extends SaveBatchCIContext> contextMap = ciSwitchSvc.saveOrUpdateBatchCI(coverCiList, classIds, ownerCode, loginCode, libType);
            List<ESCIInfo> dbCiList = contextMap.values().stream().map(SaveBatchCIContext::getEsCi).collect(Collectors.toList());
            Map<String, String> relIdMap = modelSvc.createModelCategory(diagramId, dbCiList, ownerCode, libType);
            List<ESCIClassInfo> classList = ciClassApiSvc.selectCiClassByIds(classIds);
            Map<Long, ESCIClassInfo> classMap = classList.stream().collect(Collectors.toMap(ESCIClassInfo::getId, each -> each));
            for (ESCIInfo ciInfo : dbCiList) {
                ESCIClassInfo classInfo = classMap.get(ciInfo.getClassId());
                CcCiInfo ccCiInfo = EamUtil.coverESCIInfo(ciInfo, EamUtil.copy(classInfo.getAttrDefs(), CcCiAttrDef.class), classInfo);
                CiInfoExtend extendCi = EamUtil.copy(ccCiInfo, CiInfoExtend.class);
                extendCi.setCurrentDiagramId(relIdMap.get(ciInfo.getCiCode()));
                rMap.put(ciInfo.getCiCode(), extendCi);
            }
        }
        ControllerUtils.returnJson(request, response, rMap);
    }

    @PostMapping("/enableRemoveCiFromView")
    @Deprecated
    public void enableRemoveCiFromView(HttpServletRequest request, HttpServletResponse response, @RequestBody EamCategoryCdt removeData) {
        BinaryUtils.checkEmpty(removeData.getCiCodes(), "ciCode");
        long success = eamCiSvc.enableRemoveCiFromView(removeData.getCiCodes(), removeData.getDiagramId(), removeData.getOwnerCode(), removeData.getLibType());
        ControllerUtils.returnJson(request, response, !(success > 0L));
    }

    @ModDesc(desc = "通过ID查询对象信息", pDesc = "对象的id", pType = Long.class, rDesc = "对象信息", rType = CcCiInfo.class)
    @RequestMapping("/queryById")
    public void queryById(@RequestParam(defaultValue = "DESIGN") LibType libType,
                          HttpServletRequest request, HttpServletResponse response, @RequestParam Long id) {
        //Long id = Long.parseLong(body.trim());
        CcCiInfo result = ciSwitchSvc.getCiInfoById(id, libType);
        ControllerUtils.returnJson(request, response, result);
    }

    @ModDesc(desc = "通过code查询对象信息", pDesc = "对象的code", pType = String.class, rDesc = "对象信息", rType = CcCiInfo.class)
    @RequestMapping("/queryByCode")
    public void queryByCode(@RequestParam(defaultValue = "DESIGN") LibType libType,
                            HttpServletRequest request, HttpServletResponse response, @RequestBody JSONObject body) {
        BinaryUtils.checkEmpty(body.getString("ciCode"), "ciCode");
        CCcCi cdt = new CCcCi();
        cdt.setCiCode(body.getString("ciCode"));
        List<CcCiInfo> result = ciSwitchSvc.queryCiInfoList(SysUtil.getCurrentUserInfo().getDomainId(), cdt, null, false, true, libType);
        if (!BinaryUtils.isEmpty(result)) {
            ControllerUtils.returnJson(request, response, result.get(0));
        } else {
            ControllerUtils.returnJson(request, response, new JSONObject());
        }
    }


    @RequestMapping("/queryPageByIndex")
    @ModDesc(desc = "分页查询对象数据", pDesc = "条件查询", pType = QueryPageCondition.class, pcType = CiQueryCdtExtend.class, rDesc = "对象数据", rType = CiGroupPage.class)
    public void queryPageByIndex(@RequestParam(defaultValue = "DESIGN") LibType libType,
                                 HttpServletRequest request, HttpServletResponse response, @RequestBody String body) {
        QueryPageCondition<CiQueryCdtExtend> pageCdt = RestTypeUtil.toPageCondition(body, CiQueryCdtExtend.class);
        CiGroupPage result = ciSwitchSvc.queryPageByIndex(pageCdt.getPageNum(), pageCdt.getPageSize(), pageCdt.getCdt(), false, libType);
        ControllerUtils.returnJson(request, response, result);
    }

    @RequestMapping("/queryPageBySearchBean")
    @ModDesc(desc = "分页查询对象数据-支持属性排序", pDesc = "条件查询", pType = QueryPageCondition.class, pcType =
            ESCISearchBean.class, rDesc = "对象数据", rType = CiGroupPage.class)
    public void queryPageBySearchBean(@RequestParam(defaultValue = "DESIGN") LibType libType,
                                      HttpServletRequest request, HttpServletResponse response,
                                      @RequestBody ESCISearchBeanVO bean) {
        isConvertibleToLong(bean);
        CiGroupPage result = ciSwitchSvc.queryPageBySearchBeanVO(bean, false, libType);
        ControllerUtils.returnJson(request, response, result);

    }

    @RequestMapping("/queryPageBySearchBeanV2")
    @ModDesc(desc = "根据分类标识分页查询对象数据-支持属性排序", pDesc = "条件查询", pType = QueryPageCondition.class, pcType =
            ESCISearchBean.class, rDesc = "对象数据", rType = CiGroupPage.class)
    public void queryPageBySearchBeanV2(@RequestParam(defaultValue = "DESIGN") LibType libType,
                                        HttpServletRequest request, HttpServletResponse response,
                                        @RequestBody ESCISearchBeanVO bean) {
        isConvertibleToLong(bean);
        if (!CollectionUtils.isEmpty(bean.getClassCodes())) {
            List<CcCiClassInfo> classInfos = ciClassApiSvc.getByClassCodes(bean.getClassCodes(), SysUtil.getCurrentUserInfo().getDomainId());
            if (CollectionUtils.isEmpty(classInfos) || classInfos.size() < bean.getClassCodes().size()) {
                throw new BinaryException("分类信息不存在");
            }
            List<Long> classIds = classInfos.stream().map(e -> e.getCiClass().getId()).collect(Collectors.toList());
            bean.getClassIds().addAll(classIds);
        }
        CiGroupPage result = ciSwitchSvc.queryPageBySearchBeanVO(bean, true, libType);
        ControllerUtils.returnJson(request, response, result);

    }

    private void isConvertibleToLong(ESCISearchBeanVO esciSearchBeanVO) {
        if (StringUtils.isNotBlank(esciSearchBeanVO.getGteTime())) {
            String gteTime = esciSearchBeanVO.getGteTime().replace("/", "");
            try {
                Long.parseLong(gteTime);
            } catch (NumberFormatException e) {
                throw new BusinessException("时间区间查询 大于等于传参有问题请核实在传入");
            }
        }
        if (StringUtils.isNotBlank(esciSearchBeanVO.getLteTime())) {
            String lteTime = esciSearchBeanVO.getLteTime().replace("/", "");
            try {
                Long.parseLong(lteTime);
            } catch (NumberFormatException e) {
                throw new BusinessException("时间区间查询 大于等于传参有问题请核实在传入");
            }
        }
        if (StringUtils.isNotBlank(esciSearchBeanVO.getGteTime()) && StringUtils.isNotBlank(esciSearchBeanVO.getLteTime())) {
            String gteTime = esciSearchBeanVO.getGteTime().replace("/", "");
            String lteTime = esciSearchBeanVO.getLteTime().replace("/", "");
            if (Long.parseLong(gteTime) > Long.parseLong(lteTime)) {
                throw new BusinessException("时间区间查询 起始时间不能大于终止时间");
            }
        }
    }

    @PostMapping("/queryClassMap")
    @ResponseBody
    public RemoteResult queryClassMap(@RequestParam(defaultValue = "DESIGN") LibType libType,@RequestBody ESCISearchBean bean) {
        CiGroupPage result = ciSwitchSvc.queryPageBySearchBean(bean, false, libType);
        List<CcCiInfo> data = result.getData();
        if (data != null && data.size() > 0) {
            return new RemoteResult(classListToMap(data));
        }
        return new RemoteResult("");
    }

    private  Map<Long, List<CcCiInfo>> classListToMap(List<CcCiInfo> data) {
        Map<Long, List<CcCiInfo>> resultMap = data.stream().collect(Collectors.groupingBy(item -> item.getCi().getClassId()));
        return resultMap;
    }

    @ResponseBody
    @PostMapping("/getCiList")
    @ModDesc(desc = "分页查询对象数据-支持属性排序", pDesc = "条件查询", pType = QueryPageCondition.class, pcType =
            ESCISearchBean.class, rDesc = "对象数据", rType = CiGroupPage.class)
    public CiGroupPage getCiList(@RequestParam(defaultValue = "DESIGN") LibType libType,
                                 @RequestBody ESCISearchBean bean) {
        return ciSwitchSvc.queryPageBySearchBean(bean, false, libType);
    }

    @PostMapping("/findCiSwitchUserList")
    @ResponseBody
    public RemoteResult findCiSwitchUserList(@RequestBody ESCISearchBean bean) {
        List<SysUser> ciSwitchUsers = ciSwitchSvc.findCiSwitchUserList(bean, false);
        return new RemoteResult(ciSwitchUsers);
    }

    @PostMapping("/queryCiInfoBySearchBean")
    @ModDesc(desc = "分页查询对象数据-支持属性排序", pDesc = "条件查询", pType = QueryPageCondition.class, pcType = ESCISearchBean.class, rDesc = "对象数据", rType = CiGroupPage.class)
    public void queryCiInfoBySearchBean(@RequestParam(defaultValue = "DESIGN") LibType libType,
                                        HttpServletRequest request, HttpServletResponse response, @RequestBody ESCISearchBean bean) {
        CiGroupPage result = this.getCiGroupList(bean, libType);
        if (result != null && result.getTotalCiCount() == 0 && !BinaryUtils.isEmpty(bean.getWords())) {
            bean.setWords(Collections.emptyList());
            result = this.getCiGroupList(bean, libType);
        }
        ControllerUtils.returnJson(request, response, result);
    }

    @RequestMapping("/queryCiInfoPage")
    @ModDesc(desc = "分页查询对象数据", pDesc = "条件查询", pType = QueryPageCondition.class, pcType = CCcCi.class, rDesc = "对象数据", rType = Page.class)
    public void queryCiInfoPage(@RequestParam(defaultValue = "DESIGN") LibType libType,
                                HttpServletRequest request, HttpServletResponse response, @RequestBody String body) {
        QueryPageCondition<CCcCi> pageCdt = RestTypeUtil.toPageCondition(body, CCcCi.class);
        Page<CcCiInfo> result = ciSwitchSvc.queryCiInfoPage(1L, pageCdt.getPageNum(), pageCdt.getPageSize(), pageCdt.getCdt(), pageCdt.getOrders(), false, true, libType);
        ControllerUtils.returnJson(request, response, result);
    }

    @RequestMapping(value = "/importCi", method = RequestMethod.POST)
    @ModDesc(desc = "通过XLS或者XLSX导入CI信息", pDesc = "XLS或者XLSX文件", rDesc = "导入明细", rType = ImportResultMessage.class)
    public void asyncImportCi(@RequestParam(defaultValue = "DESIGN") LibType libType,
                              HttpServletRequest request, HttpServletResponse response,
                              @RequestParam("file") MultipartFile file) {
        BinaryUtils.checkEmpty(request.getParameter("ciClassIds"), "ciClassIds");
        Long classId = Long.parseLong(request.getParameter("ciClassIds"));
        ImportResultMessage result = ciSwitchSvc.importCiByCiClsIds(file, classId, libType);
        ControllerUtils.returnJson(request, response, result);
    }

    @RequestMapping("/exportCi")
    @ModDesc(desc = "导出对象数据(hasData:0只导出分类及属性(默认),1:导出分类加数据;ciClassIds:分类的ID多个用','隔开,不传导出所有分类)", pDesc = "?hasData=1&ciClassIds=1", pType = String.class, rDesc = "导出全部CI", rType = String.class)
    public ResponseEntity<byte[]> exportCi(@RequestParam(defaultValue = "DESIGN") LibType libType, @RequestBody ExportCiDto exportDto) {
        return ciSwitchSvc.exportCiOrClass(exportDto, libType);
    }

    @GetMapping("/exportCiByDiagramId")
    @ModDesc(desc = "导出当前视图中的CI数据", pDesc = "?diagramId=1", pType = Long.class, rDesc = "导出当前视图中CI数据", rType = String.class)
    public ResponseEntity<byte[]> exportCiByDiagramId(@RequestParam(defaultValue = "DESIGN") LibType libType,
                                                      @RequestParam(name = "diagramId") Long diagramId) {
        return exportPeer.exportCiByDiagramId(diagramId, libType);
    }

    @RequestMapping(value = "/importCiExcelBatch", method = RequestMethod.POST)
    @ModDesc(desc = "一键导入解析Excel文件", pDesc = "XLS或者XLSX文件", pType = MultipartFile.class, rDesc = "文件解析内容", rType = ImportExcelMessage.class)
    public void importCiExcelBatch(@RequestParam(defaultValue = "DESIGN") LibType libType,
                                   HttpServletRequest request, HttpServletResponse response,
                                   @RequestParam("file") MultipartFile file) {
        ImportExcelMessage result = ciSwitchSvc.importCiExcel(file, libType);
        ControllerUtils.returnJson(request, response, result);
    }

    @RequestMapping(value = "/importCiByClassBatch", method = RequestMethod.POST)
    @ModDesc(desc = "一键导入批量导入分类数据", pDesc = "导入对象", pType = CiExcelInfoDto.class, rDesc = "导入明细", rType = ImportResultMessage.class)
    public void importCiByClassBatch(@RequestParam(defaultValue = "DESIGN") LibType libType,
                                     HttpServletRequest request, HttpServletResponse response,
                                     @RequestBody CiExcelInfoDto excelInfoDto) {
        ImportResultMessage result = ciSwitchSvc.importCiByClassBatch(excelInfoDto, libType);
        ControllerUtils.returnJson(request, response, result);
    }

    @GetMapping("/removeById")
    @ModDesc(desc = "通过ID删除对象", pDesc = "对象的ID", pType = Long.class, rDesc = "1成功0失败", rType = Integer.class)
    public void removeById(@RequestParam(defaultValue = "DESIGN") LibType libType,
                           HttpServletRequest request, HttpServletResponse response, @RequestParam Long id) {
        //long id = Long.parseLong(body.trim());
        Integer integer = ciSwitchSvc.removeById(id, 1L, libType);
        ControllerUtils.returnJson(request, response, integer);
    }

    @RequestMapping("/removeByIds")
    @ModDesc(desc = "通过ID批量删除对象", pDesc = "对象的ID集合", pType = List.class, pcType = Long.class, rDesc = "1成功0失败", rType = Integer.class)
    public void removeByIds(@RequestParam(defaultValue = "DESIGN") LibType libType,
                            HttpServletRequest request, HttpServletResponse response, @RequestBody List<Long> ciIds) {
        Integer result = ciSwitchSvc.removeByIds(ciIds, 1L, libType);
        ControllerUtils.returnJson(request, response, result);
    }

    @RequestMapping("/removeByClassId")
    @ModDesc(desc = "通过分类ID删除相关的对象数据", pDesc = "对象分类的ID", pType = Long.class, rDesc = "1成功0失败", rType = Integer.class)
    public void removeByClassId(@RequestParam(defaultValue = "DESIGN") LibType libType,
                                HttpServletRequest request, HttpServletResponse response, @RequestBody String body) {
        long id = Long.parseLong(body.trim());
        Integer integer = ciSwitchSvc.removeByClassId(id, 1L, libType);
        ControllerUtils.returnJson(request, response, integer);
    }

    @RequestMapping("/removeByOwnerCode")
    @ModDesc(desc = "根据用户删除相关分类的对象数据", pDesc = "对象分类的ID", pType = Long.class, rDesc = "1成功0失败", rType = Integer.class)
    public void removeByOwnerCodeAndClassId(
            @RequestParam(defaultValue = "DESIGN") LibType libType,
            HttpServletRequest request, HttpServletResponse response, @RequestBody String body) {
        JSONObject json = JSON.parseObject(body);
        Long classId ;
        if (json.containsKey("classId")) {
            classId = json.getLong("classId");
        } else {
            throw new ServiceException("classId不能为空");
        }
        String ownerCode = null;
        if (json.containsKey("ownerCode")) {
            ownerCode = json.getString("ownerCode");
        }
        Integer integer = ciSwitchSvc.removeByOwnerCodeAndClassId(libType, classId, ownerCode);
        ControllerUtils.returnJson(request, response, integer);
    }

    @RequestMapping("/searchCIByBean")
    @ModDesc(desc = "条件搜索对象数据", pDesc = "查询条件", pType = ESCISearchBean.class, rDesc = "对象数据", rType = CcCiSearchPage.class)
    public void searchCIByBean(@RequestParam(defaultValue = "DESIGN") LibType libType,
                               @RequestBody ESCISearchBean bean, HttpServletRequest request,
                               HttpServletResponse response) {
        Long domainId = SysUtil.getCurrentUserInfo().getDomainId();
        bean.setDomainId(domainId);
        if(!LibType.PRIVATE.equals(libType)){
            bean.setOwnerCode(null);
        }else {
            if (bean.getOwnerCode() == null) {
                bean.setOwnerCode(SysUtil.getCurrentUserInfo().getLoginCode());
            }
        }
        CcCiSearchPage res = ciSwitchSvc.searchCIByBean(bean, libType);
        ControllerUtils.returnJson(request, response, res);
    }

    @RequestMapping("/queryCiInfoList")
    @ModDesc(desc = "分页查询对象数据", pDesc = "条件查询", pType = QueryPageCondition.class, pcType = CCcCi.class, rDesc = "对象数据", rType = List.class)
    public void queryCiInfoList(@RequestParam(defaultValue = "DESIGN") LibType libType,
                                HttpServletRequest request, HttpServletResponse response, @RequestBody String body) {

        QueryPageCondition<CCcCi> pageCdt = RestTypeUtil.toPageCondition(body, CCcCi.class);

        // 接口传参的ciCodes[]为空 会导致searchESCIByBean方法查询用户全量 做个处理 这个接口将不支持除了ciCodes以外的字段去查询
        List<CcCiInfo> ciInfos = new ArrayList<>();
        if (!BinaryUtils.isEmpty(pageCdt.getCdt().getCiCodes())) {
            ESCISearchBean bean = new ESCISearchBean();
            bean.setPageNum(1);
            bean.setPageSize(3000);
            bean.setCdt(pageCdt.getCdt());
            bean.setDomainId(SysUtil.getCurrentUserInfo().getDomainId());
            if (LibType.PRIVATE == libType) {
                JSONObject params = JSONObject.parseObject(body);
                String ownerCode = params.getString("ownerCode");
                if (BinaryUtils.isEmpty(ownerCode)) {
                    ownerCode = SysUtil.getCurrentUserInfo().getLoginCode();
                }
                bean.setOwnerCode(ownerCode);
            }
            Page<ESCIInfo> page = ciSwitchSvc.searchESCIByBean(bean, libType);
            Set<Long> classIds = page.getData().stream().map(ESCIInfo::getClassId).collect(Collectors.toSet());

            List<ESCIClassInfo> esciClassInfos = ciClassApiSvc.selectCiClassByIds(new ArrayList<>(classIds));
            Map<Long, ESCIClassInfo> classMap = esciClassInfos.stream().collect(Collectors.toMap(ESCIClassInfo::getId, each -> each));
            Map<Long, List<ESCIAttrDefInfo>> classAttrMap = new HashMap<>();
            esciClassInfos.forEach(e -> {
                classAttrMap.put(e.getId(), e.getAttrDefs());
            });

            for (ESCIInfo ciInfo : page.getData()) {
                ESCIClassInfo classInfo = classMap.get(ciInfo.getClassId());
                CcCiInfo ci = EamUtil.coverESCIInfoOptimize(ciInfo, EamUtil.copy(classAttrMap.get(ciInfo.getClassId()), CcCiAttrDef.class), classInfo);
                ciInfos.add(ci);
            }
        }
        ControllerUtils.returnJson(request, response, ciInfos);
    }

    @RequestMapping("/queryCiInfoListByCiCodes")
    @ModDesc(desc = "分页查询对象数据", pDesc = "条件查询", pType = QueryPageCondition.class, pcType = CCcCi.class, rDesc = "对象数据", rType = List.class)
    public void queryCiInfoListByCiCodes(@RequestParam(defaultValue = "DESIGN") LibType libType,
                                         HttpServletRequest request, HttpServletResponse response, @RequestBody String body) {
        QueryPageCondition<CCcCi> pageCdt = RestTypeUtil.toPageCondition(body, CCcCi.class);
        String[] ciCodes = pageCdt.getCdt().getCiCodes();
        if (ciCodes.length < 1) {
            ControllerUtils.returnJson(request, response, Collections.emptyList());
            return;
        }
        ESCISearchBean bean = new ESCISearchBean();
        bean.setPageNum(1);
        bean.setPageSize(3000);
        bean.setCdt(pageCdt.getCdt());
        bean.setCiCodes(Lists.newArrayList(ciCodes));
        bean.setDomainId(SysUtil.getCurrentUserInfo().getDomainId());
        if (LibType.PRIVATE == libType) {
            JSONObject params = JSONObject.parseObject(body);
            String ownerCode = params.getString("ownerCode");
            if (BinaryUtils.isEmpty(ownerCode)) {
                ownerCode = SysUtil.getCurrentUserInfo().getLoginCode();
            }
            bean.setOwnerCode(ownerCode);
        }
        Page<ESCIInfo> page = ciSwitchSvc.searchESCIByBean(bean, libType);
        Set<Long> classIds = page.getData().stream().map(ESCIInfo::getClassId).collect(Collectors.toSet());
        List<ESCIClassInfo> esciClassInfos = ciClassApiSvc.selectCiClassByIds(new ArrayList<>(classIds));
        Map<Long, ESCIClassInfo> classMap = esciClassInfos.stream().collect(Collectors.toMap(ESCIClassInfo::getId, each -> each));
        List<CcCiInfo> ciInfos = new ArrayList<>();
        for (ESCIInfo ciInfo : page.getData()) {
            ESCIClassInfo classInfo = classMap.get(ciInfo.getClassId());
            CcCiInfo ci = EamUtil.coverESCIInfo(ciInfo, EamUtil.copy(classInfo.getAttrDefs(), CcCiAttrDef.class), classInfo);
            ciInfos.add(ci);
        }
        ControllerUtils.returnJson(request, response, ciInfos);

    }

    @PostMapping("/queryCiInfoListByCiCodes/withoutCiClass")
    @ModDesc(desc = "分页查询对象数据", pDesc = "条件查询", pType = QueryPageCondition.class, pcType = CCcCi.class, rDesc = "对象数据", rType = List.class)
    public RemoteResult queryCiInfoListByCiCodesWithoutCiClass(@Valid @RequestBody CiInfoQueryVo ciInfoQueryVo) {
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        Long domainId = SysUtil.getCurrentUserInfo().getDomainId();
        query.must(QueryBuilders.termQuery("domainId", domainId));
        query.must(QueryBuilders.termsQuery("ciCode.keyword", ciInfoQueryVo.getCiCodes()));
        if (LibType.PRIVATE == ciInfoQueryVo.getLibType()) {
            query.must(QueryBuilders.termQuery("ownerCode.keyword", SysUtil.getCurrentUserInfo().getLoginCode()));
        }
        List<SortBuilder<?>> sorts = new ArrayList<>();
        sorts.add(SortBuilders.fieldSort("id").order(SortOrder.ASC));
        Page<ESCIInfo> page = ciSwitchSvc.getESCIInfoPageByQuery(domainId, 1, 3000, query, sorts, false, ciInfoQueryVo.getLibType());
        List<CcCiInfo> ciInfos = new ArrayList<>();
        for (ESCIInfo ciInfo : page.getData()) {
            CcCiInfo ci = EamUtil.coverESCIInfo(ciInfo, null, null);
            ciInfos.add(ci);
        }
        return new RemoteResult(ciInfos);
    }

    @RequestMapping("/getFigureCiInfo")
    @ModDesc(desc = "分页查询部署架构图对象数据", pDesc = "条件查询", pType = QueryPageCondition.class, pcType = CCcCi.class, rDesc = "对象数据", rType = List.class)
    public void getFigureCiInfo(@RequestParam(defaultValue = "DESIGN") LibType libType,
                                HttpServletRequest request, HttpServletResponse response, @RequestBody String body) {
        QueryPageCondition<CCcCi> pageCdt = RestTypeUtil.toPageCondition(body, CCcCi.class);
        String[] ciCodes = pageCdt.getCdt().getCiCodes();
        if(ciCodes.length<1){
            ControllerUtils.returnJson(request,response, Collections.emptyList());
        }else {
            List<CcCiInfo> result = ciSwitchSvc.queryCiInfoList(SysUtil.getCurrentUserInfo().getDomainId(), pageCdt.getCdt(), null, false, true, libType);
            List<VcCiInfo> vcCiInfos = convertToVcCiInfoResult(result);
            vcCiInfos.forEach(each -> {
                each.setAttrDefs(null);
                each.setAttrsMap(null);
            });
            ControllerUtils.returnJson(request, response, vcCiInfos);
        }
    }


    @RequestMapping("/queryPageCiTableByCiCodes")
    @ModDesc(desc = "查询对象列表数据", pDesc = "条件查询", pType = QueryPageCondition.class, pcType = CCcCi.class, rDesc = "对象数据", rType = List.class)
    public void queryPageCiTableByCiCodes(@RequestParam(defaultValue = "DESIGN") LibType libType,
                                          HttpServletRequest request, HttpServletResponse response, @RequestBody String body) {
        QueryPageCondition<CCcCi> pageCdt = RestTypeUtil.toPageCondition(body, CCcCi.class);
        String[] ciCodes = pageCdt.getCdt().getCiCodes();
        VcCiTableInfo ciTable = new VcCiTableInfo();
        Page<Map<String, String>> rPage = new Page<>(pageCdt.getPageNum(), pageCdt.getPageSize(), 0, 0, Collections.emptyList());
        ciTable.setAttrValuePage(rPage);
        if (ciCodes.length < 1) {
            ControllerUtils.returnJson(request, response, ciTable);
            return;
        }
        Long queryClassId = pageCdt.getCdt().getClassId();
        pageCdt.getCdt().setClassId(null);
        List<CcCi> ciList = ciSwitchSvc.queryCiList(SysUtil.getCurrentUserInfo().getDomainId(), pageCdt.getCdt(), null, false, libType);
        if (CollectionUtils.isEmpty(ciList)) {
            ControllerUtils.returnJson(request, response, ciTable);
            return;
        }
        List<Long> classIds = ciList.stream().map(CcCi::getClassId).distinct().collect(Collectors.toList());
        List<ESCIClassInfo> ciClassList = ciClassApiSvc.selectCiClassByIds(classIds);
        if (null == queryClassId || queryClassId == 0) {
            queryClassId = ciClassList.get(0).getId();
        }
        pageCdt.getCdt().setClassId(queryClassId);
        final long matchClassId = queryClassId;
        List<VcCiTableInfo.VcCiClassTabs> ciClassTabs = ciClassList.stream().map((each) -> {
            VcCiTableInfo.VcCiClassTabs ciClassTab = new VcCiTableInfo.VcCiClassTabs();
            ciClassTab.setClassId(each.getId());
            ciClassTab.setClassName(each.getClassName());
            ciClassTab.setSelectEnable(each.getId().equals(matchClassId));
            return ciClassTab;
        }).collect(Collectors.toList());
        ciTable.setCiClassTabs(ciClassTabs);

        Page<CcCiInfo> ccCiInfoPage = ciSwitchSvc.queryCiInfoPage(SysUtil.getCurrentUserInfo().getDomainId(), pageCdt.getPageNum(), pageCdt.getPageSize(), pageCdt.getCdt(), null, false, true, libType);
        rPage.setTotalPages(ccCiInfoPage.getTotalPages());
        rPage.setTotalRows(ccCiInfoPage.getTotalRows());
        List<CcCiAttrDef> defs = ccCiInfoPage.getData().get(0).getAttrDefs();
        List<String> heads = defs.stream().map(CcCiAttrDef::getProName).collect(Collectors.toList());
        ciTable.setCiAttrHeads(heads);
        List<Map<String, String>> attrValues = ccCiInfoPage.getData().stream().map(CcCiInfo::getAttrs).collect(Collectors.toList());
        rPage.setData(attrValues);
        ControllerUtils.returnJson(request, response, ciTable);
    }

    @RequestMapping(value = "/searchCiPage", method = RequestMethod.POST)
    public void searchCiPage(@RequestParam(defaultValue = "DESIGN") LibType libType,
                             HttpServletRequest request, HttpServletResponse response, @RequestBody ESCISearchBean bean) {
        if ((libType == LibType.PRIVATE && BinaryUtils.isEmpty(bean.getOwnerCode()))) {
            bean.setOwnerCode(SysUtil.getCurrentUserInfo().getLoginCode());
        }
        if ((libType != LibType.PRIVATE && !BinaryUtils.isEmpty(bean.getOwnerCode()))) {
            bean.setOwnerCode(null);
        }
        String filterColumn = request.getHeader(StaticParamUtil.STATIC_SEARCHCI_ONLYCICODE);
        CcCiSearchPage ciInfoPage = ciSwitchSvc.searchCIByBean(bean, libType);
        Page<VcCiInfo> results = FormatUtil.esCiDtoToCmvDtoWithoutAttrDefs(ciInfoPage);
        if (!BinaryUtils.isEmpty(filterColumn) && StaticParamUtil.STATIC_SEARCHCI_ONLYCICODE.equals(filterColumn)) {
            List<String> datas = new LinkedList<>();
            if (results.getData() != null) {
                for (VcCiInfo data : results.getData()) {
                    datas.add(data.getCi().getCiCode());
                }
            }
            Page<String> realResults = new Page<>(results.getPageNum(), results.getPageSize(), results.getTotalRows(), results.getTotalPages(), datas);
            ControllerUtils.returnJson(request, response, realResults);
        } else {
            ControllerUtils.returnJson(request, response, results);
        }
    }

    @PostMapping(value = "/queryCiCountByClass")
    @ModDesc(desc = "按指定条件查询CI，并按分类进行汇总", pDesc = "查询条件", pType = CiQueryCdt.class, rDesc = "CI分类列表", rType = List.class)
    public void queryCiCountByClass(@RequestParam(defaultValue = "DESIGN") LibType libType,
                                    HttpServletRequest request, HttpServletResponse response, @RequestBody CiQueryCdtExtend cdt) {
        if (LibType.PRIVATE.equals(libType) && cdt != null) {
            String systemClassCode = getSystemCICLassCode();
            cdt.setIgnoreCiClassCodes(Collections.singletonList(systemClassCode));
        }
        List<VcCiClassInfoDto> result = eamCiSvc.queryCiCountByClass(cdt, libType);
        ControllerUtils.returnJson(request, response, result);
    }

    private String getSystemCICLassCode() {
        String configJson = bmConfigSvc.getConfigType("AXEA_CONFIG");
        if (org.apache.commons.lang3.StringUtils.isBlank(configJson)) {
            throw new BinaryException("未查询到国投配置，请联系管理员");
        }
        JSONObject conf = JSON.parseObject(configJson);
        if (conf == null) {
            throw new BinaryException("未查询到国投分类映射配置，请联系管理员");
        }
        String axeaClassMapping = conf.getString("classMapping");
        if (StringUtils.isBlank(axeaClassMapping)) {
            throw new BinaryException("未查询到国投系统分类映射配置，请联系管理员");
        }
        JSONObject axeaClassConf = JSONObject.parseObject(axeaClassMapping);
        String systemClassCode = axeaClassConf.getString("systemClassCode");
        if (StringUtils.isBlank(systemClassCode)) {
            throw new BinaryException("未查询到国投系统分类映射配置，请联系管理员");
        }
        return systemClassCode;
    }

    @PostMapping(value = "/checkCiAttrs")
    public void checkCiAttrs(HttpServletRequest request, HttpServletResponse response, @RequestBody CheckCIAttr check) {
        if (CollectionUtils.isEmpty(check.getIds())) {
            ControllerUtils.returnJson(request, response, Collections.emptyMap());
            return;
        }
        Map<Long, String> errMap = eamCiSvc.checkCiAttrs(check);
        ControllerUtils.returnJson(request, response, errMap);
    }

    @GetMapping("/getLibTypes")
    @ResponseBody
    public RemoteResult getLibTypes() {
        if (BinaryUtils.isEmpty(libTypes)) {
            return new RemoteResult(LibType.BASELINE);
        }
        return new RemoteResult(libTypes);
    }

    private List<VcCiInfo> convertToVcCiInfoResult(List<CcCiInfo> result) {
        ArrayList<VcCiInfo> vcCiInfos = new ArrayList<>();
        for (CcCiInfo ccCiInfo : result) {
            Map<String, String> attrs = ccCiInfo.getAttrs();
            VcCiInfo vcCiInfo = new VcCiInfo();
            BeanUtils.copyProperties(ccCiInfo, vcCiInfo);
            List<AttrInfo> attrsList = new ArrayList<>();
            List<CcCiAttrDef> attrDefs = vcCiInfo.getAttrDefs();
            for (CcCiAttrDef attrDef : attrDefs) {
                String key = attrDef.getProName();
                AttrInfo attrInfo = new AttrInfo();
                attrInfo.setKey(key);
                attrInfo.setValue(attrs.get(key));
                attrsList.add(attrInfo);
            }
            vcCiInfo.setAttrs(attrsList);
            vcCiInfo.setAttrsMap(ccCiInfo.getAttrs());
            vcCiInfos.add(vcCiInfo);
        }
        return vcCiInfos;
    }

    /**
     * 查询对象分类树结构
     */
    @RequestMapping("/getClassTree")
    public RemoteResult getClassTree(@RequestParam(defaultValue = "false") Boolean display, @RequestParam(defaultValue = "BASELINE") LibType libType) {
        List<ClassNodeInfo> result = ciSwitchSvc.getClassTree(display, libType);
        return new RemoteResult(result);
    }

    @GetMapping("/findClassManagerList")
    public void findClassManagerList(@RequestParam(value = "classId", required = false) Long classId,
                                     HttpServletRequest request, HttpServletResponse response) {
        List<ClassNodeInfo> ls = ciSwitchSvc.findClassManagerList(classId);
        ControllerUtils.returnJson(request, response, ls);
    }

    /**
     * 验证ci在私有库/共享库是否已存在
     *
     */
    @PostMapping("/handleCiExist")
    @ResponseBody
    public RemoteResult handleCiExist(@RequestBody String body) {
        JSONObject json = JSONObject.parseObject(body);
        List<Long> ids = JSONObject.parseArray(json.getString("ids"), Long.class);
        String libType = json.getString("libType");
        LibType typeData = LibType.valueOf(libType);
        String ownerCode = json.getString("ownerCode");
        Integer result = eamCiSvc.handleCiExist(ids, typeData, ownerCode);
        return new RemoteResult(result);
    }

    @RequestMapping("/queryPageByAllIndex")
    @ModDesc(desc = "通过索引查询相关的CI", pDesc = "查询条件", pType = QueryPageCondition.class, pcType = CiQueryCdtExtend.class, rDesc = "CI的信息", rType = VcCiSearchPage.class)
    public void queryPageByAllIndex(HttpServletRequest request, HttpServletResponse response, @RequestBody QueryPageCondition<CiQueryCdtExtend> pageCdt) {
        int pageSize = pageCdt.getPageSize();
        if (pageSize < 1) {
            throw new ServiceException("is wrong pageSize '" + pageSize + "'! ");
        }
        List<VcCiSearchPage> result = ciSwitchSvc.queryPageByAllIndex(pageCdt.getPageNum(), pageCdt.getPageSize(), pageCdt.getCdt(), pageCdt.getOrders(), new VcCiQ[]{VcCiQ.ATTR});
        ControllerUtils.returnJson(request, response, result);
    }

    @RequestMapping("/queryEnumDataByClassId")
    public void queryEnumDataByClassId(HttpServletRequest request, HttpServletResponse response, @RequestBody CiQueryCdt cdt) {
        Map<Long, List<String>> result = ciSwitchSvc.queryEnumDataByClassId(cdt.getClassId());
        ControllerUtils.returnJson(request, response, result);
    }

    @RequestMapping("/getPrivateCIInfoByDesginCode")
    public void getPrivateCIInfoByDesginCode(HttpServletRequest request, HttpServletResponse response,
                                             @RequestBody(required = false) String ciCode) {
        CcCiInfo privateCIInfo = ciSwitchSvc.getPrivateCIInfoByDesginCode(ciCode);
        ControllerUtils.returnJson(request, response, privateCIInfo);
    }

    /**
     * 元模型删除分类前校验该分类下是否存在数据
     */
    @RequestMapping("/existDataByClassId")
    @ModDesc(desc = "分页查询对象数据", pDesc = "条件查询", pType = QueryPageCondition.class, pcType = CiQueryCdtExtend.class, rDesc = "对象数据", rType = CiGroupPage.class)
    public void existDataByClassId(HttpServletRequest request, HttpServletResponse response, @RequestBody String body) {
        QueryPageCondition<CiQueryCdtExtend> pageCdt = RestTypeUtil.toPageCondition(body, CiQueryCdtExtend.class);
        Map<String, Long> result = ciSwitchSvc.existDataByClassId(pageCdt.getCdt());
        ControllerUtils.returnJson(request, response, result);
    }

    /**
     * 查询CI属性值
     */
    @RequestMapping(value = "/queryValues", method = RequestMethod.POST)
    @ResponseBody
    public RemoteResult queryValues(@RequestBody QueryCiValueRequest request) {

        List<String> data = eamCiSvc.queryValues(request);
        return new RemoteResult(data);
    }

    @PostMapping("/findNonCompliance")
    public void findNonCompliance(@RequestParam Long classId,@RequestParam(defaultValue = "BASELINE") LibType libType,HttpServletRequest request,
                                  HttpServletResponse response) {
        boolean result = ciSwitchSvc.findNonCompliance(classId,libType);
        ControllerUtils.returnJson(request, response, result);
    }

    @RequestMapping("/exportCiByConditions")
    public ResponseEntity<byte[]> exportCiByConditions(@RequestParam(defaultValue = "DESIGN") LibType libType, @RequestBody ExportCiVO exportDto) {
        ESCISearchBeanVO esciSearchBeanVO = new ESCISearchBeanVO();
        esciSearchBeanVO.setGteTime(exportDto.getGteTime());
        esciSearchBeanVO.setLteTime(exportDto.getLteTime());
        isConvertibleToLong(esciSearchBeanVO);
        return ciSwitchSvc.exportCiOrClassByConditions(exportDto, libType);
    }

    /**
     * 资产可见->筛选数据
     * @param bean
     * @param libType
     * @return
     */
    private CiGroupPage getCiGroupList(ESCISearchBean bean, LibType libType) {
        if (!StringUtils.isEmpty(bean.getDiagramId())) {
            CiGroupPage ciGroupPage = getCiGroupPage(bean, libType);
            if (ciGroupPage != null) {
                return ciGroupPage;
            }
        }
        bean.setDiagramId(null);
        return ciSwitchSvc.queryPageBySearchBean(bean, false, libType);
    }

    private CiGroupPage getCiGroupPage(ESCISearchBean bean, LibType libType) {
        ESDiagram esDiagram = diagramApiClient.getEsDiagram(bean.getDiagramId(), 0);
        if (esDiagram == null || !Objects.equals(esDiagram.getDiagramSubType(), 2) || StringUtils.isEmpty(esDiagram.getViewType())) {
            return null;
        }
        List<EamArtifactElementVo> elementList = artifactColumnSvc.queryByArtifactId(Long.valueOf(esDiagram.getViewType()), Lists.newArrayList(ArtifactType.ASSET_TYPE.val()));
        if (BinaryUtils.isEmpty(elementList)) {
            return null;
        }
        Map<Long, String> filterMap = new HashMap<>();
        Set<Long> artifactClassIds = new HashSet<>();
        for (EamArtifactElementVo artifactElementVo : elementList) {
            List<String> elements = artifactElementVo.getElements();
            for (String element : elements) {
                EamArtifactCiVo vo = JSON.parseObject(element, EamArtifactCiVo.class);
                if (BinaryUtils.isEmpty(vo.getType()) || !vo.getType().equals("class") || !vo.getAssetsFlag()) {
                    continue;
                }
                artifactClassIds.add(Long.valueOf(vo.getId()));
                List<Long> classIds = bean.getClassIds();
                if (!StringUtils.isEmpty(vo.getFilter()) && classIds.contains(Long.valueOf(vo.getId()))) {
                    filterMap.put(Long.valueOf(vo.getId()), vo.getFilter());
                }
            }
        }
        List<ESAttrBean> orAttrs = getOrAttrsIfNeed(bean, artifactClassIds);
        if (!CollectionUtils.isEmpty(orAttrs)) {
            bean.setOrAttrs(orAttrs);
        }
        if (LibType.DESIGN.equals(libType) && !CollectionUtils.isEmpty(filterMap)) {
            int size = bean.getPageSize();
            for (Map.Entry<Long, String> filterInfo : filterMap.entrySet()) {
                List<Long> classList = new ArrayList<>(1);
                classList.add(filterInfo.getKey());
                bean.setClassIds(classList);
                // 获取过滤条件
                String filterStr = filterInfo.getValue();
                if (!com.binary.core.lang.StringUtils.isEmpty(filterStr)) {
                    JSONArray jsonArray = JSONArray.parseArray(filterStr);
                    if (jsonArray.size() > 0) {
                        List<CcCiInfo> allClassCiList = new ArrayList<>();
                        for (int i = 0; i < jsonArray.size(); i++) {
                            JSONArray jsonArr = jsonArray.getJSONArray(i);
                            List<ESAttrBean> andAttrs = new ArrayList<>();
                            for (int j = 0; j < jsonArr.size(); j++) {
                                JSONObject filterJson = jsonArr.getJSONObject(j);
                                if (filterJson != null && !StringUtils.isEmpty(filterJson.getString("name"))
                                        && !StringUtils.isEmpty(filterJson.getString("value"))) {
                                    ESAttrBean esAttrBean = new ESAttrBean();
                                    esAttrBean.setKey(filterJson.getString("name"));
                                    esAttrBean.setOptType(1);
                                    esAttrBean.setValue(filterJson.getString("value"));
                                    andAttrs.add(esAttrBean);
                                }
                            }
                            bean.setAndAttrs(andAttrs);
                            bean.setDiagramId(null);
                            bean.setPageSize(3000);
                            CiGroupPage page = ciSwitchSvc.queryPageBySearchBean(bean, false, libType);
                            if (page != null && !CollectionUtils.isEmpty(page.getData())) {
                                if (page.getTotalRows() > 3000) {
                                    bean.setPageSize((int)page.getTotalRows());
                                    page = ciSwitchSvc.queryPageBySearchBean(bean, false, libType);
                                }
                                List<CcCiInfo> ciList = page.getData();
                                allClassCiList.addAll(ciList);
                            }
                        }
                        if (!CollectionUtils.isEmpty(allClassCiList)) {
                            // ci去重
                            List<CcCiInfo> collect = new ArrayList<>(allClassCiList.size());
                            Set<String> ciCodeSet = new HashSet<>(allClassCiList.size());
                            for (CcCiInfo ccCiInfo : allClassCiList) {
                                if (!ciCodeSet.contains(ccCiInfo.getCi().getCiCode())) {
                                    collect.add(ccCiInfo);
                                    ciCodeSet.add(ccCiInfo.getCi().getCiCode());
                                }
                            }
                            int records = collect.size();
                            int del = records / size;
                            int mod = records % size;
                            Integer total = (mod != 0) ? del + 1 : del;
                            CiGroupPage ciGroupPage = new CiGroupPage(bean.getPageNum(), size, records, total, collect);
                            ciGroupPage.setTotalCiCount(records);
                            return ciGroupPage;
                        }
                    }
                }
            }
        }
        return null;
    }

    private List<ESAttrBean> getOrAttrsIfNeed(ESCISearchBean bean, Set<Long> artifactClassIds) {
        //此需求仅针对画布左侧资产列表单个分类数据查询场景，此时根据资产限制引用情况做过滤
        if (CollectionUtils.isEmpty(bean.getClassIds()) || bean.getClassIds().size() > 1) {
            return new ArrayList<>();
        }
        Long ciClassId = bean.getClassIds().get(0);
        //不在制品下跳过
        if (!artifactClassIds.contains(ciClassId)) {
            return new ArrayList<>();
        }
        //视图绑定资产
        EamDiagramRelationSys diagramRelationSys = diagramRelationSysService.getEamDiagramRelationSys(bean.getDiagramId());
        if (diagramRelationSys == null || StringUtils.isBlank(diagramRelationSys.getEsSysId())) {
            return new ArrayList<>();
        }
        String diagramBindAssertCiCode = diagramRelationSys.getEsSysId();
        //绑定资产分类
        List<ESCIInfo> bindCiInfos = ciSwitchSvc.getCiByCodes(Arrays.asList(diagramBindAssertCiCode), null, LibType.DESIGN);
        if (CollectionUtils.isEmpty(bindCiInfos)) {
            return new ArrayList<>();
        }
        //制品下的分类有无限制引用
        List<CiClassLimitUseDetail> limitUseDetails = ciClassLimitUseSvc.details(Collections.singleton(ciClassId));
        if (CollectionUtils.isEmpty(limitUseDetails)) {
            return new ArrayList<>();
        }
        List<ESAttrBean> orAttrs = new ArrayList<>();
        CiClassLimitUseDetail detail = limitUseDetails.get(0);
        if (detail.getRelateClassId().equals(bindCiInfos.get(0).getClassId())) {
            List<CcCiAttrDef> limitAttrDefs = detail.getLimitAttrDefs();
            for (CcCiAttrDef limitAttrDef : limitAttrDefs) {
                ESAttrBean orAttr = new ESAttrBean();
                orAttr.setKey(limitAttrDef.getProName());
                orAttr.setOptType(2);
                orAttr.setValue("\"ciCode\":\"" + diagramBindAssertCiCode + "\"");
                orAttrs.add(orAttr);
            }
        }
        return orAttrs;
    }

    @PostMapping("/primaryKey/check")
    @ModDesc(desc = "校验主键完整性", pDesc = "对象标识", pType = String.class, rDesc = "是否完整", rType = Boolean.class)
    public RemoteResult checkPrimaryKey(@RequestBody String body) {
        JSONObject param = JSON.parseObject(body);
        String ciCode = param.getString("ciCode");
        String ownerCode = param.getString("ownerCode");
        Boolean result = eamCiSvc.checkPrimaryKey(ciCode, ownerCode);
        return new RemoteResult(result);
    }

    @PostMapping("/queryReleCiInfo")
    @ModDesc(desc = "分页查询对象数据-支持属性排序,添加数据筛选", pDesc = "条件查询", pType = QueryPageCondition.class, pcType = ESCiReleAssetSearchBean.class, rDesc = "对象数据", rType = CiGroupPage.class)
    public void queryReleCiInfo(@RequestParam(defaultValue = "DESIGN") LibType libType,
                                HttpServletRequest request, HttpServletResponse response, @RequestBody ESCiReleAssetSearchBean bean) {

        CiGroupPage result = ciSwitchSvc.queryReleCiInfo(bean, libType);
        Page<Map> page = new Page<>();
        page.setPageNum(result.getPageNum());
        page.setPageSize(result.getPageSize());
        page.setTotalPages(result.getTotalPages());
        page.setTotalRows(result.getTotalRows());
        List<Map> data = new ArrayList<>();
        result.getData().forEach(e->{
            HashMap<String, String> ciInfo = new HashMap<>();
            ciInfo.put("ciCode", e.getCi().getCiCode());
            ciInfo.put("ciLabel", getLabel(e.getCi()));
            String ciPrimaryKey = e.getCi().getCiPrimaryKey();
            List<String> ciPrimaryList = JSONObject.parseArray(ciPrimaryKey, String.class);
            ciPrimaryList.remove(0);
            ciInfo.put("primary", ciPrimaryList.stream().collect(Collectors.joining("\\|")));
            data.add(ciInfo);
        });
        page.setData(data);
        ControllerUtils.returnJson(request, response, page);
    }

    private String getLabel(CcCi ci) {
        String ciLabel = ci.getCiLabel();
        if (StringUtils.isBlank(ciLabel)) {
            return null;
        }
        List<String> datas = JSONObject.parseArray(ciLabel, String.class);
        if (CollectionUtils.isEmpty(datas)) {
            return null;
        }
        return String.join(" ", datas);
    }

    @ApiOperation("获取关联ci对应属性值列表-添加数据筛选")
    @PostMapping("/getAttrValuesBySearchBean")
    public ApiResult<Page<CcCiInfo>> getAttrValuesBySearchBean(@RequestBody ESAttrAggScreenBean bean) {
        return  ApiResult.ok(this).data(eamCiSvc.getAttrValuesBySearchBean(bean));
    }

}